/**
 * 
 */
package com.jie.eclipse.pan.utils.handle;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.internal.resources.File;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jst.jsp.core.internal.domdocument.DOMDocumentForJSP;
import org.eclipse.jst.jsp.core.internal.domdocument.ElementImplForJSP;
import org.eclipse.jst.jsp.core.internal.domdocument.TextImplForJSP;
import org.eclipse.ui.editors.text.TextFileDocumentProvider;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.document.DOMModelImpl;
import org.eclipse.wst.xml.core.internal.document.ElementImpl;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeIterator;

import com.jie.eclipse.pan.config.BaseConfig;
import com.jie.eclipse.pan.data.BaseDataEntities;
import com.jie.eclipse.pan.data.BaseDataEntity;
import com.jie.eclipse.pan.editors.PLLFormEditor;
import com.jie.eclipse.pan.editors.form.PllDetailPage;
import com.jie.eclipse.pan.editors.form.PllPage;
import com.jie.eclipse.pan.utils.StringHelper;
import com.jie.eclipse.pan.utils.Utils;
import com.jie.eclipse.pan.xml.XMLNode;

/**
 * @author yanjie
 *
 */
@SuppressWarnings("restriction")
public class FileHandle {
	private PllDetailPage detailPage = null;
	IStructuredModel uiSM = null;
	IDOMDocument uidomDoc = null;
	/**
	 * @return the uidomDoc
	 */
	public IDOMDocument getUidomDoc() {
		return uidomDoc;
	}

	public FileHandle(PllDetailPage detailPage) {
		this.detailPage = detailPage;
		IModelManager modelManager = StructuredModelManager.getModelManager();
		PLLFormEditor formeditor = (PLLFormEditor)((PllPage)this.detailPage.getFormPage()).getEditor();
		
		try {
			this.uiSM = modelManager.getModelForEdit(formeditor.getUiInput().getFile());
			this.uidomDoc = ((DOMModelImpl)this.uiSM).getDocument();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	public FileHandle(File file){
		try {
			IModelManager modelManager = StructuredModelManager.getModelManager();
			this.uiSM = modelManager.getModelForEdit(file);
			this.uidomDoc = ((DOMModelImpl)this.uiSM).getDocument();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	public void modelToXml(){
		modelToXml(null);
	}
	
	public void modelToXml(Object elment){
		if(this.detailPage.getCurComposite() == null) return;
		XMLNode curNode = this.detailPage.getCurNode();
		if("table".equalsIgnoreCase(curNode.getNodeName()) && elment != null){
			//编辑表格节点属性
			BaseDataEntity record = this.detailPage.getCurComposite().getDataBind().getRecord();
			if(elment instanceof BaseDataEntities ){
				record.spov("tablecolumn", (BaseDataEntities)elment);
				curNode.loadData(record,false);
			}
		}else if("tablecolumn".equalsIgnoreCase(curNode.getNodeName())){
			//编辑表格栏位节点属性
			curNode.loadData(this.detailPage.getCurComposite().getDataBind().getRecord(),true);
		}else{
			curNode.loadSelfData(this.detailPage.getCurComposite().getDataBind().getRecord());
		}
		
		saveXml();
		saveJSP(elment);
	}
	
	public void saveXml(){
		XMLNode curNode = this.detailPage.getCurNode();
		if("tablecolumn".equalsIgnoreCase(curNode.getNodeName())){
			curNode.spsv(BaseConfig.TAG_LABLE, curNode.gpsv("caption"));
			TreeViewer tv = this.getPllpage().getBlock().getTreeViewer();//取得左边树的查看器
			tv.refresh(curNode.getParentNode(), true);
		}
		
		PLLFormEditor pllFormEditor =  (PLLFormEditor)this.detailPage.getFormPage().getEditor();
		StructuredTextEditor pllEditor = pllFormEditor.getPllEditor();
		TextFileDocumentProvider tfp= (TextFileDocumentProvider)pllEditor.getDocumentProvider();
		JobSafeStructuredDocument jsd = (JobSafeStructuredDocument)tfp.getDocument(pllFormEditor.getEditorInput());
		jsd.set(XMLNode.Export(((PllPage) this.detailPage.getFormPage()).getPageNode()));
	}
	
	/**
	 * @param elment
	 * 保存JSP
	 */
	public void saveJSP(Object elment){
		if(this.detailPage.getCurComposite() == null || this.uiSM == null) return;
		XMLNode curNode = this.detailPage.getCurNode();
		if("page".equalsIgnoreCase(curNode.getNodeName())){//编辑 页面属性
			modifyPageProperty(curNode);
		}else if("table".equalsIgnoreCase(curNode.getNodeName()) && elment != null){//编辑 页面属性
			modifyTable(curNode);
		}else if("tablecolumn".equalsIgnoreCase(curNode.getNodeName())){
			modifyTableColumnProperty(curNode);
		}
	}
	
	
	/**
	 * @param elments
	 * 刪除行
	 */
	public void deleteTableRows(Object[] elments){
		if( elments == null ) return ;
		XMLNode curNode = this.detailPage.getCurNode();
		for (int i = 0; i < elments.length; i++) {
			if(elments[i] instanceof BaseDataEntity){
				//刪除xml中的行
				curNode.DeleteChildNodeByNodeNameAndId("tablecolumn", ((BaseDataEntity)elments[i]).gpsv("id"));
				//刪除jsp中行
				this.deleteJspTableRows((BaseDataEntity)elments[i]);
			}
		}
		saveXml();
	}
	
	/**
	 * @param data
	 * 刪除jsp中的表格行
	 */
	public void deleteJspTableRows(BaseDataEntity data){
		XMLNode curNode = this.detailPage.getCurNode();
		Element table = this.getTableById(this.uidomDoc,curNode.getID());
		
		int index = -1;
		//tbody 中的td
		Element tbody = this.getElement(table, "tagname=jm:tbody");
		Element td2 = null;
		if(tbody != null){
			td2 = this.getElement(tbody, "tagname=jm:td|cid="+data.gpsv("cid"));
			index = this.getIndexInNodeList(tbody.getElementsByTagName("jm:td"), td2);
			if(td2 != null){
				Element tr2 =  this.getElement(tbody, "tagname=jm:tr");
				tr2.removeChild(td2);
			}
		}
		
		//thead 中 td
		if(index >= 0){
			Element thead = this.getElement(table, "tagname=jm:thead");
			Element td1 = null;
			if(thead != null){
				td1 = (Element)this.getNodebyIndex(thead.getElementsByTagName("td"), index);
				if(td1 != null){
					Element tr1 =  this.getElement(thead, "tagname=tr");
					tr1.removeChild(td1);
				}
			}
		}
		
	}
	
	/**
	 * @param curNode
	 * 修改表格节点
	 */
	public void modifyTable(XMLNode curNode){
		Element table = this.getTableById(this.uidomDoc,curNode.getID());
		modifyTableProperty(table,curNode);//修改表格节点属性
		
		if(table == null){
			Element center = this.getElement(this.uidomDoc, "tagname=jm:layout|postion=center");
			String center_text0 = this.getContentText(center);
			String center_text1 = "\r\n"+center_text0+"	";
			
			center.appendChild(this.uidomDoc.createTextNode(center_text1));
			table = this.uidomDoc.createElement("jm:table");
			table.setAttribute("id", curNode.getID());
			center.appendChild(table);
			center.appendChild(this.uidomDoc.createTextNode("\r\n"+center_text0));
		}
		
		if(table != null){
			String text0 = this.getContentText(table);;
			String text1 = "\r\n"+text0+"    ";//tbody thead
			String text2 = text1+"	";//tr
			String text3 = text2+"	";//td
			//取出表头
			Element thead = this.getElement(table, "tagname=jm:thead");
			if(thead == null){
				thead = this.uidomDoc.createElement("jm:thead");
				table.appendChild(this.uidomDoc.createTextNode(text1));
				table.appendChild(thead);
			}
			
			boolean btr1 = true;
			Element tr1 = this.getElement(thead, "tagname=tr");
			if(tr1 == null){
				btr1 = false;
				tr1 = this.uidomDoc.createElement("tr");
				thead.appendChild(this.uidomDoc.createTextNode(text2));
				thead.appendChild(tr1);
				thead.appendChild(this.uidomDoc.createTextNode(text1));
				table.appendChild(this.uidomDoc.createTextNode(text1));
			}
			
			Element tbody = this.getElement(table, "tagname=jm:tbody");
			if(tbody == null){
				tbody = this.uidomDoc.createElement("jm:tbody");
				table.appendChild(tbody);
				tbody.appendChild(this.uidomDoc.createTextNode(text2));
				table.appendChild(this.uidomDoc.createTextNode("\r\n"+text0));		
			}
			
			boolean btr2 = true;
			Element tr2 = this.getElement(tbody, "tagname=jm:tr");
			if(tr2 == null){
				btr2 = false;
				tr2 = this.uidomDoc.createElement("jm:tr");
				tbody.appendChild(tr2);
				tbody.appendChild(this.uidomDoc.createTextNode(text1));
			}
			
			
			BaseDataEntities rows = curNode.getChildBaseDataEntities();
			for (int i = 0; i < rows.size(); i++) {
				BaseDataEntity row = rows.get(i);
				//标题
				Element td1 = (Element)this.getNodebyIndex(tr1.getElementsByTagName("td"), i); 
				if(td1 == null){
					td1 = this.uidomDoc.createElement("td");
					tr1.appendChild(this.uidomDoc.createTextNode(text3));
					tr1.appendChild(td1);
				}else{
					if(td1.getFirstChild() != null)
						td1.removeChild(td1.getFirstChild());
				}
				td1.appendChild(this.uidomDoc.createTextNode(row.gpsv("caption")));
				if(!row.isNullOrEmpty("width")){
					td1.setAttribute("width", row.gpsv("width")+(
							(row.gpsv("width").endsWith("px")
									|| row.gpsv("width").equals("*")
									|| row.gpsv("width").endsWith("%"))  
										? "" : "px"));
				}else{
					td1.removeAttribute("width");
				}
				
				//tbody
				Element td2 = (Element)this.getNodebyIndex(tr2.getElementsByTagName("jm:td"), i);
				if(td2 == null){
					td2 = this.uidomDoc.createElement("jm:td");
					tr2.appendChild(this.uidomDoc.createTextNode(text3));
					tr2.appendChild(td2);
				}
				td2.setAttribute("cid",row.gpsv("cid"));
			}
			
			if(!btr1)
				tr1.appendChild(this.uidomDoc.createTextNode(text2));
			if(!btr2)
				tr2.appendChild(this.uidomDoc.createTextNode(text2));
		}
	}
	
	/**
	 * @param columnNode
	 * 修改table属性
	 */
	public void modifyTableProperty(Element table,XMLNode tableNode){
		if(table == null || tableNode == null)return;
		//数据源
		if(!tableNode.isNullOrEmpty("dataSet")){
			if("default".equalsIgnoreCase(tableNode.gpsv("dataSet"))){
				table.setAttribute("dataSet", "<%=ret.getSerchResult()%>");
			}else{
				table.setAttribute("dataSet", "<%=ret.gpov(\""+tableNode.gpsv("dataSet")+"\")%>");
			}
		}else{
			table.removeAttribute("dataSet");
		}
		//空值循环一次
		if(tableNode.gpbv("loopFisrt", false)){
			table.setAttribute("loopFisrt", "true");
		}else{
			table.removeAttribute("loopFisrt");
		}
		//锁表头
		if(!tableNode.isNullOrEmpty("view") && "fixedRow".equals(tableNode.gpsv("view"))){
			table.setAttribute("view", "fixedRow");
		}else{
			table.removeAttribute("view");
		}
		//表格工具栏
		if(tableNode.gpbv("toolbar", false)){
			table.setAttribute("toolbar", "true");
		}else{
			table.removeAttribute("toolbar");
		}
	}
	
	/**
	 * @param columnNode
	 * 修改td属性
	 */
	public void modifyTableColumnProperty(XMLNode columnNode){
		int index = columnNode.getIndexInParentChildNodes();
		if(index < 0) return ;
		
		Element table = this.getTableById(this.uidomDoc,columnNode.getParentNode().getID());
		if(table != null){
			Element thead = this.getElement(table, "tagname=jm:thead");
			ElementImplForJSP td1 = null;
			if(thead != null){
				td1 = (ElementImplForJSP)this.getNodebyIndex(thead.getElementsByTagName("td"), index);
				if(td1 != null){
					td1.removeChildNodes();
					td1.appendChild(this.uidomDoc.createTextNode(columnNode.gpsv("caption")));
					
					if(!StringHelper.IsNullOrEmpty(columnNode.gpsv("width"))){
						td1.setAttribute("width", 
								columnNode.gpsv("width")
								+(
										(columnNode.gpsv("width").endsWith("px")
												||columnNode.gpsv("width").endsWith("*")
												||columnNode.gpsv("width").endsWith("%"))  
													? "" : "px"));
					}else{
						td1.removeAttribute("width");
					}
				}
			}
			
			Element tbody = this.getElement(table, "tagname=jm:tbody");
			ElementImplForJSP td2 = null;
			if(tbody != null){
				td2 = (ElementImplForJSP)this.getNodebyIndex(tbody.getElementsByTagName("jm:td"), index);
				if(td2 != null){
					td2.setAttribute("cid", columnNode.gpsv("cid"));
					if("static".equalsIgnoreCase(columnNode.gpsv("edit"))){
						Element childElement = getTdChildElement(columnNode);
						if(childElement != null){
							td2.removeChildNodes();
							td2.appendChild(childElement);
						}
					}
				}
			}
		}
	}
	
	/**
	 * @return
	 * 返回td绘制器
	 */
	public Element getTdChildElement(XMLNode columnNode){
		if(columnNode == null)return null;
		XMLNode editorNode = columnNode.GetChildNodeByNodeName("editor");
		if(editorNode == null)return null;
		String editType =  editorNode.gpsv("editType").toLowerCase();
		
		String strStyle = "";
		if("text".equals(editType)){
			Element el = this.uidomDoc.createElement("input");
			el.setAttribute("type", "text");
			this.setElAtribute(el, editorNode, "id",editorNode.getID());
			this.setElAtribute(el, editorNode, "name");
			this.setElAtribute(el, editorNode, "value");
			
			
			if(!editorNode.isNullOrEmpty("width")){
				strStyle += (strStyle.length() > 0 ? ";" : "")+"width:"+editorNode.gpsv("width")+(editorNode.gpsv("width").endsWith("px") ? "" : "px")+";";
			}
			
			this.setElAtribute(el, editorNode, "style",strStyle);
			return el;
		}else if("select".equals(editType)){
			Element el = this.uidomDoc.createElement("jm:select");
			this.setElAtribute(el, editorNode, "id",editorNode.getID());
			this.setElAtribute(el, editorNode, "name");
			this.setElAtribute(el, editorNode, "value");
			this.setElAtribute(el, editorNode, "codeList");
			this.setElAtribute(el, editorNode, "dataSource");
			this.setElAtribute(el, editorNode, "sql");
			if(!editorNode.isNullOrEmpty("width")){
				strStyle += (strStyle.length() > 0 ? ";" : "")+"width:"+editorNode.gpsv("width")+(editorNode.gpsv("width").endsWith("px") ? "" : "px")+";";
			}
			
			this.setElAtribute(el, editorNode, "style",strStyle);
			
			return el;
		}else if("radio".equals(editType)){
			Element el = this.uidomDoc.createElement("jm:radio");
			this.setElAtribute(el, editorNode, "id",editorNode.getID());
			this.setElAtribute(el, editorNode, "name");
			this.setElAtribute(el, editorNode, "value");
			this.setElAtribute(el, editorNode, "codeList");
			return el;
		}else if("checkbox".equals(editType)){
			Element el = this.uidomDoc.createElement("jm:checkbox");
			this.setElAtribute(el, editorNode, "id",editorNode.getID());
			this.setElAtribute(el, editorNode, "name");
			this.setElAtribute(el, editorNode, "withHidden");
			this.setElAtribute(el, editorNode, "codeList");
			return el;
		}
		return null;
	}
	
	public void setElAtribute(Element el,XMLNode node,String name){
		setElAtribute(el, node, name,node.gpsv(name));
	}
	/**
	 * @param el
	 * @param node
	 * @param name
	 * 设置节点属性
	 */
	public void setElAtribute(Element el,XMLNode node,String name,String value){
		if(!StringHelper.IsNullOrEmpty(value)){
			if(value.indexOf("ret.") >= 0){
				value = "<%="+value+"%>";
			}
			el.setAttribute(name, value);
		}else{
			el.removeAttribute(name);
		}
	}
	
	/**
	 * @param curNode
	 * 修改頁面屬性 標題等
	 */
	public void modifyPageProperty(XMLNode curNode){
		ElementImplForJSP node = this.getPageProperty(this.uidomDoc,false);
		if(node == null)return;
		String str = node.getTextContent();
		str = str.replaceAll("page1.getPageTitle\\(\\).setTitle\\(\"([^\"]*)\"\\)", 
				"page1.getPageTitle().setTitle(\""+curNode.gpsv("pageTitle")+"\")");
		try {
			node.removeChildNodes();
			node.appendChild(this.uidomDoc.createTextNode(str));
		} catch (Exception e) {
			Utils.print(e.getMessage());
		}
	}
	
	/**
	 * @param elment
	 * @param tableid
	 * @return
	 * 根据id取出表格节点
	 */
	public ElementImplForJSP getTableById(Object elment,String tableid){
		if(StringHelper.IsNullOrEmpty(tableid)) return null;
		
		if(elment instanceof DOMDocumentForJSP){
			Element el =((DOMDocumentForJSP)elment).getElementById(tableid);
			if(el instanceof ElementImplForJSP){
				return (ElementImplForJSP)el;
			}
		}
		return null;
	}

	/**
	 * @param elment
	 * @param bclose
	 * @return
	 */
	public ElementImplForJSP getPageProperty(Object elment,boolean bclose){
		if(elment instanceof IDOMDocument){
			NodeList list = ((IDOMDocument)elment).getChildNodes();
			for (int i = 0; i < list.getLength(); i++) {
				Node node = list.item(i);
				if(node instanceof ElementImplForJSP){
					ElementImplForJSP rs = getPageProperty(node,bclose);
					if(rs != null) return rs;
					
					ElementImplForJSP jspElement = (ElementImplForJSP)node;
					if(jspElement.getStartStructuredDocumentRegion().getText().indexOf("head2.jsp") > 0){
						bclose = true;
					}
				}
			}
		}
		
		if(elment instanceof ElementImplForJSP){
			ElementImplForJSP node = (ElementImplForJSP)elment;
			if(bclose && "jsp:scriptlet".equalsIgnoreCase(node.getNodeName())){
				return node;
			}
		}
		return null;
	}
	
	/**
	 * @param root
	 * @param strSelect
	 * @return
	 * 根据选择器返回节点 
	 */
	public Element getElement(Node root,String strSelect) {
		if (StringHelper.IsNullOrEmpty(strSelect))
			return null;
		List rule = new ArrayList();
		for (int i = 0; i < strSelect.split("[|]").length; i++) {
			rule.add(strSelect.split("[|]")[i]);
		}
		
		NodeIterator it = ((DOMDocumentForJSP)this.uidomDoc).createNodeIterator(root,-1, null, false);
		if (it == null) {
			return null;
		}
		for (Node node = it.nextNode(); node != null; node = it.nextNode()) {
			if (node.getNodeType() != 1)
				continue;
			ElementImpl element = (ElementImpl) node;
			boolean bvalid = true;
			for (int i = 0; i < rule.size(); i++) {
				String[] op = rule.get(i).toString().split("=");
				if("tagname".equalsIgnoreCase(op[0])){
					if(!op[1].equalsIgnoreCase(element.getTagName())){
						bvalid = false;
						break;
					}
				}else if("text".equalsIgnoreCase(op[0])){
					if(!op[1].equalsIgnoreCase(element.getTextContent())){
						bvalid = false;
						break;
					}
				}else if(!element.hasAttribute(op[0]) || !op[1].equalsIgnoreCase(element.getAttribute(op[0]))){
					bvalid = false;
					break;
				}
			}
			if (bvalid) {
				return element;
			}
		}
		return null;
	}
	
	/**
	 * @param elment
	 * @return
	 * 取出当前节点的缩进字符
	 */
	public String getContentText(Element elment){
		Node node = elment.getPreviousSibling();
		if(node == null) return "";
		if(node instanceof TextImplForJSP){
			TextImplForJSP text = (TextImplForJSP)node;
			String strText = text.getTextContent();
			String texts[] = strText.split("\\r\\n");
			return texts[texts.length-1];
		}
		return "";
	}
	
	public Node getNodebyIndex(NodeList nodeList,int index){
		if(nodeList != null && index < nodeList.getLength()){
			return nodeList.item(index);
		}
		return null;
	}
	
	public int getIndexInNodeList(NodeList nodeList,Node node){
		if(nodeList == null)return -1;
		for (int i = 0; i < nodeList.getLength(); i++) {
			if(nodeList.item(i) == node)
				return i;
		}
		return -1;
	}
	
	public PllDetailPage getDetailPage() {
		return detailPage;
	}
	
	public PllPage getPllpage(){
		return (PllPage)this.detailPage.getFormPage();
	}
	
	public PLLFormEditor getPllFormEditor(){
		return (PLLFormEditor)this.getPllpage().getEditor();
	}
}
